package com.jackchen.dao.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.Serializable;

import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.HibernateException;
import java.sql.SQLException;

import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.hibernate.Session;

import com.jackchen.dao.IBaseDAO;
import com.jackchen.po.Pager;

public class IBaseDAOImpl extends HibernateDaoSupport implements IBaseDAO {
	
	private static final Logger log = Logger.getLogger(IBaseDAOImpl.class);
	
	public <E> E findById(Class<E> entityClass, Serializable id) {
		return this.getHibernateTemplate().get(entityClass, id);
	}
	
	public Map findByPage(String aClassName,final int aPageSize,final int aStartRow){
		log.debug("finding instances by page!");
		try {
			Map queryResult = new HashMap();
			List resultList = new ArrayList();
			final String queryHQL = " from "+aClassName;
			List allRecords=this.getHibernateTemplate().find("select count(*) from "+aClassName);
			if(null!=allRecords&&allRecords.size()>0){
				Long totalRecordsLong = (Long)allRecords.get(0);
				Integer totalRecordsNum = new Integer(totalRecordsLong.intValue());
				Pager page = new Pager(totalRecordsNum,aPageSize);
				resultList = this.getHibernateTemplate().executeFind(new HibernateCallback() {
					public Object doInHibernate(Session session) throws HibernateException, SQLException {
						Query query = session.createQuery(queryHQL);
						query.setFirstResult(aStartRow);
						query.setMaxResults(aPageSize);
						List list = query.list();
						return list;
					}
				});
				queryResult.put("querylist", resultList);
				queryResult.put("pager", page);
				return queryResult;
			}else{
				queryResult.put("querylist", resultList);
				queryResult.put("pager", null);
				return queryResult;
			}
			
			
		} catch (RuntimeException re) {
			log.error("find all failed", re);
			throw re;
		}
		
	}
	
	public List findAll(String aClassName) throws DataAccessException {
		String queryHQL = " from "+aClassName;
		List allRecords=this.getHibernateTemplate().find(queryHQL);
		return allRecords;
	}
	
	//-------------------------------------------------------------------------
	// @Author:华文涛
	//为将接口暴露给外部调用，以下方法全部都为(Override)重写HibernateTemplate相应方法，方法同名，
	// 参数同名，具体调用方法可见Spring API手册中HibernateTemplate类的API用法。IBaseDAO这个接口，
	//我已在每个方法前有简略的注释用法信息,参见IBaseDAO接口方法前注释说明.
	//-------------------------------------------------------------------------
	
	@Override
	public List findByNamedQuery(String queryName, Object value) throws DataAccessException{
		return this.getHibernateTemplate().findByNamedQuery(queryName,value);
	}
	
	@Override
	public List findByNamedQuery(String queryName, Object... values){
		return this.getHibernateTemplate().findByNamedQuery(queryName,values);
	}
	 
	public List findByNamedParam(String queryString, String paramName, Object value)
			throws DataAccessException{
		return findByNamedParam(queryString, new String[] {paramName}, new Object[] {value});
	}
	
	public List findByNamedParam(final String queryString, final String[] paramNames, final Object[] values)
			throws DataAccessException{
		return this.getHibernateTemplate().findByNamedParam(queryString, paramNames, values);
	}
	
	@Override
	public Serializable save(final Object entity){
		return this.getHibernateTemplate().save(entity);
	}
	
	@Override
	public void update(Object entity) throws DataAccessException{
		this.getHibernateTemplate().update(entity);
	}
	
	@Override
	public void saveOrUpdate(final Object entity) throws DataAccessException{
		this.getHibernateTemplate().saveOrUpdate(entity);
	}
	
	public void saveOrUpdateAll(final List entities) throws DataAccessException{
		this.getHibernateTemplate().saveOrUpdateAll(entities);
	}
	
	@Override
	public void delete(Object entity) throws DataAccessException{
		this.getHibernateTemplate().delete(entity);
	}
	
	@Override
	public <T> void deleteById(Class<T> entityClass, Serializable id) throws DataAccessException{
		T entity =  findById(entityClass, id);
		this.getHibernateTemplate().delete(entity);
	}
	
	public void deleteAll(final List entities) throws DataAccessException{
		this.getHibernateTemplate().deleteAll(entities);
	}
	
	public <T> void sessionLoad(Class<T> entityClass,Serializable id){
		this.getHibernateTemplate().load(entityClass, id);
	}
	
	@Override
	public List findByExample(Object exampleEntity) throws DataAccessException{
		return this.getHibernateTemplate().findByExample(exampleEntity);
	}
	
	@Override
	public <T> T merge(final String entityName, final T entity) throws DataAccessException{
		return this.getHibernateTemplate().merge(entityName,entity);
	}
	
	@Override
	public List<Object> findObjBySql(String sql, Object... objects) {
		Query q = getSession().createSQLQuery(sql);
		for (int i = 0; i < objects.length; i++) {
			q.setParameter(i, objects[i]); 
		}
		return q.list();
	
	}
	
	@Override
	public List<Object> findObjByHSql(String sql, Object... objects) {
		Query q = getSession().createQuery(sql);
		for (int i = 0; i < objects.length; i++) {
			q.setParameter(i, objects[i]);
		}
		return q.list();
	
	}

	@Override
	public Map findObjBySqlPage(String sql, final int aPageSize, final int aStartRow, Object... objects) {
		final Query q = getSession().createQuery(sql);
		for (int i = 0; i < objects.length; i++) {
			q.setParameter(i, objects[i]);
		}
		
		Map queryResult = new HashMap();
		List resultList = Collections.emptyList();
		List allRecords = this.getHibernateTemplate().find("select count(*) " + q.getQueryString());
		if(null != allRecords && allRecords.size() > 0){
			Long totalRecordsLong = (Long)allRecords.get(0);
			Integer totalRecordsNum = new Integer(totalRecordsLong.intValue());
			Pager page = new Pager(totalRecordsNum,aPageSize);
			q.setFirstResult(aStartRow);
			q.setMaxResults(aPageSize);
			resultList = q.list();
			queryResult.put("querylist", resultList);
			queryResult.put("pager", page);
			return queryResult;
		} else {
			queryResult.put("querylist", resultList);
			queryResult.put("pager", null);
			return queryResult;
		}
	}
	
	@Override
	public List<Object> findObjByColumn(String tableName, Object... objs) {
		String hql = "from "+tableName;
		if(objs.length%2==1){
			return null;
		}
		Object param[] = new Object[objs.length/2];
		if(objs.length>0){
			hql += " where ";
			for(int i=0;i<objs.length;i++){
				hql += objs[i] +"=? and ";
				param[i] = objs[++i];
			}
		}
		if(hql.endsWith("and ")){
			hql = hql.substring(0, hql.length()-5);
		}
		List<Object> result = findObjByHSql(hql, param);
		return result;
	}
}
